#pragma once

#include <vector>
#include <shared_mutex>
#include <mutex>
#include <condition_variable>
#include <ctime>
#include <chrono>

namespace lurpc {


/**
 * Concurrent ring buffer<br>
 * 线程安全的环状队列，以数组实现，有大小限制
 *
 * @tparam T type
 */
template<typename T>
class ring_buffer {
public:
    using self_t = ring_buffer<T>;
    using item_t = T;
    using item_p = T *;
    using item_r = T &;
    using item_rr = T &&;

public:
    ring_buffer();
    ring_buffer(const ring_buffer&) = delete;
    explicit ring_buffer(size_t sz);

public:
    ~ring_buffer();

public:
    ring_buffer& operator = (const ring_buffer&) = delete;

public:
    void push(T _val);
    void wait_and_push(T _val, long long _milliseconds);
    void pop();
    void wait_and_pop(long long _milliseconds);
    T back();
    T poll();
    T wait_and_poll(long long _milliseconds);
    size_t size();
    [[nodiscard]] size_t capacity() const;

private:
    const size_t _cap;
    size_t _size;
    size_t add_p;
    size_t del_p;
    std::vector<T> _buf;
    std::mutex add_mut;
    std::mutex del_mut;
    std::condition_variable add_cv;
    std::condition_variable del_cv;
};


template<typename T>
ring_buffer<T>::ring_buffer() : ring_buffer(0) {
}

template<typename T>
ring_buffer<T>::ring_buffer(size_t sz) : _cap(sz), _size(0), add_p(0), del_p(0) {
    _buf.resize(sz);
}

template<typename T>
ring_buffer<T>::~ring_buffer() = default;

template<typename T>
void ring_buffer<T>::push(T _val) {
    if (_cap == 0) throw std::runtime_error("push to 0-capacity ring buffer");

}

template<typename T>
void ring_buffer<T>::wait_and_push(T _val, long long _milliseconds) {
}

template<typename T>
void ring_buffer<T>::pop() {
    if (_cap == 0) throw std::runtime_error("pop from 0-capacity ring buffer");
}

template<typename T>
void ring_buffer<T>::wait_and_pop(long long _milliseconds) {
}

template<typename T>
T ring_buffer<T>::back() {
    if (_cap == 0) throw std::runtime_error("get item from 0-capacity ring buffer");
    return {};
}

template<typename T>
T ring_buffer<T>::poll() {
    if (_cap == 0) throw std::runtime_error("poll from 0-capacity ring buffer");
    return {};
}

template<typename T>
T ring_buffer<T>::wait_and_poll(long long _milliseconds) {
    return {};
}

template<typename T>
size_t ring_buffer<T>::size() {
    if (_cap == 0) return 0;
    return 0;
}

template<typename T>
size_t ring_buffer<T>::capacity() const {
    return _cap;
}


}
